package com.lemurian.bankdata.action.business;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.validation.SkipValidation;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

import com.lemurian.bankdata.dto.LogHelper;
import com.lemurian.bankdata.lite.authentication.BankDataPrincipal;
import com.lemurian.bankdata.lite.enums.UserActivityType;
import com.lemurian.bankdata.lite.enums.UserStatus;
import com.lemurian.bankdata.lite.enums.UserType;
import com.lemurian.bankdata.lite.logger.BankDataLogger;
import com.lemurian.bankdata.lite.struts.Pager;
import com.lemurian.bankdata.lite.struts.PartialList;
import com.lemurian.bankdata.lite.utils.GeneralConstant;
import com.lemurian.bankdata.lite.utils.GlobalFunction;
import com.lemurian.bankdata.services.ActivityLogService;
import com.lemurian.bankdata.services.ClientService;
import com.lemurian.bankdata.services.UserService;
import com.lemurian.bankdata.utils.BaseAction;
import com.lemurian.entity.Client;
import com.lemurian.entity.User;
import com.opensymphony.xwork2.Preparable;

public class DelegasiAOAction extends BaseAction implements Preparable{

	private static final long serialVersionUID = -3514866560898272497L;
	
	private BankDataLogger log = BankDataLogger.getLogger(DelegasiAOAction.class.getSimpleName());
	
	private int id = 0;
	
	private String namaDebitur = "";
	private Client client = new Client();
	private List<Client> listClient;
	private String[] selectedRows;
	private String[] selectedAO;
	
	
	private String message = "";
	
	private User user;
	private BankDataPrincipal principal;
	
	@Autowired private ClientService clientService;
	@Autowired private UserService userService;
	@Autowired private ActivityLogService userActivityLogService;
	
	private LogHelper userActivityLog;

	private List<User> listAO = new ArrayList<User>();
	
	@Override
	public void prepare() throws Exception {
		try {
			principal = (BankDataPrincipal) getSession().get(GeneralConstant.USER_PRINCIPAL);
			user = principal.getUser();
			
			log.sInfo("GOT CLIENT ID [%s]", id);
	        if (id > 0) {
	        	client = clientService.load(id);
	        	log.info("Client found [%s]", client.getDebitur().getName());
	        }
		} catch (NullPointerException npe) {
			npe.printStackTrace();
			log.info("CLIENT IS NULL");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	@SkipValidation
	public String list() {
		log.info("list client yang akan didelegasikan");
		setPreviousPage(GeneralConstant.LIST);
		
		try {
			PartialList<Client> partialList = clientService.findByCriteria(getStart(), getCount(),
					getAscDesc().equalsIgnoreCase("desc") ? Order.desc(getOrderBy().length() > 0 ? getOrderBy() : "debitur.name") : Order.asc(getOrderBy().length() > 0 ? getOrderBy() : "debitur.name"),
					namaDebitur != null && !namaDebitur.equalsIgnoreCase("") ? Restrictions.ilike("debitur.name", namaDebitur, MatchMode.ANYWHERE) : Restrictions.ne("id", new Integer(-1)),
							Restrictions.eq("acceptedStatus", 2)
                    );

            listClient = partialList.getList();
            log.sInfo("found [%s] listClient", listClient.size());
            
            // Collecting AO
            log.sInfo("UserType ID [%s]", UserType.ACCOUNT_OFFICER.id());
            Criterion userTypeAO = Restrictions.eq("userType.id", UserType.ACCOUNT_OFFICER.id());
            Criterion activeUser = Restrictions.eq("status", UserStatus.ACTIVE.code());
            List<User> listAORaw = userService.findByCriteria(Order.asc("name"), userTypeAO, activeUser);
            
            List<String> aoUsernames = new ArrayList<String>();
            for (User ao : listAORaw) {
            	if (aoUsernames.contains(ao.getLoginId())) {
					continue;
				} else {
					aoUsernames.add(ao.getLoginId());
					listAO.add(ao);
				}
			}
            log.sInfo("found [%s] account officer", listAO.size());

            setPager(Pager.generatePager(getStart(), getCount(), partialList.getTotal()));
            setPagerItem(Pager.generatePagerItem(getStart(), getCount(), partialList.getTotal()));

            partialList = null;
            
		} catch (Exception e) {
			e.printStackTrace();
		}
        setMappedRequest(GeneralConstant.SAVE);
        return SUCCESS;

	}

	@Override
	public String save() {
		try {
			// Set Sertifikat yang didelegasikan
			if (selectedRows == null || selectedRows.length == 0) {
				addCustomActionError("Tentukan sertifikat terlebih dahulu");

	    		setMappedRequestFullPath("/DelegasiAOAction_list.do");
	            return GeneralConstant.REDIRECT;
			}
			
			log.sInfo("Total Checked [%s]", selectedRows.length);
			for (int i = 0; i < selectedRows.length; i++) {
				log.sInfo("Rows check [%s]", selectedRows[i]);
				if (selectedAO != null && selectedAO.length != 0) {
					for (int j = 0; j < selectedAO.length; j++) {
						if (selectedAO[j] != null && !selectedAO[j].equalsIgnoreCase("")) {
							String[] aoValue = selectedAO[j].split(";");
							String[] cValue = selectedRows[i].split(";");
							int cIndex = Integer.parseInt(cValue[1]);
							int aoIndex = Integer.parseInt(aoValue[1]);
							log.sInfo("cIndex [%s], aoIndex [%s]", cIndex, aoIndex);
							
							if (aoIndex == cIndex) {
								log.sInfo("Delegate klien [%s] to AO [%s]", cValue[0], aoValue[0]);
								int clientId = Integer.parseInt(GlobalFunction.decodeParameter(cValue[0]));
								int aoId = Integer.parseInt(GlobalFunction.decodeParameter(aoValue[0]));
								log.sInfo("cId [%s], aoId [%s]", clientId, aoId);
								Client client = clientService.findById(clientId);
								if (client != null) {
									log.sInfo("found client with debitur name [%s]", client.getDebitur().getName());
								}
								User ao = userService.findById(aoId);
								if (client != null) {
									log.sInfo("found ao with name [%s]", ao.getName());
								}
								
								client.setAccountOfficer(ao);
								client.setMarketingHead(user);
								client.setCreateDate(new Timestamp(System.currentTimeMillis()));
								try {
									clientService.save(client);
									
									userActivityLog = new LogHelper(user, UserActivityType.DELEGATE_AO_FOR_CLIENT);
									
						            try {
						                log.sInfo(" :: User [%s:%s] is successfully delegate [%s] to ao [%s]", user.getId(), user.getName(), client.getDebitur().getName(), ao.getName());

						                //check if activity is success
						                userActivityLog.setStatus(LogHelper.SUCCESS_ACTIVITY);
						            } catch (Exception e) {
						                log.sInfo(" :: Error was raised when User [%s:%s] delegate [%s] to ao [%s]", user.getId(), user.getName(), client.getDebitur().getName(), ao.getName());
						                
						                //set activity log status into failed
						                userActivityLog.setStatus(LogHelper.FAILED_ACTIVITY);
						                userActivityLog.setErrorMsg(e.getMessage());
						            }
						            //save activity log
						            userActivityLog.setSessionId(ServletActionContext.getRequest().getSession().getId());
						            userActivityLog.getAdditionalParams().add(client.getDebitur().getName());
						            userActivityLog.getAdditionalParams().add(ao.getName());
						            userActivityLogService.saveUserActivity(userActivityLog);
									
								} catch (Exception e) {
									e.printStackTrace();
								    message += "Maaf terjadi kesalahan, message : "+e.getMessage();
						            addCustomActionError(message);
						    		setMappedRequestFullPath("/PersetujuanKlienAction_list.do");
						            return GeneralConstant.REDIRECT;
								}
								message = "Pendelegasi Account Officer berjalan dengan sukses";
					            addCustomActionMessage(message);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		    message = "Maaf terjadi kesalahan, message : "+e.getMessage();
            addActionError(message);
		}
		setMappedRequestFullPath("/DelegasiAOAction_list.do");
        return GeneralConstant.REDIRECT;
        
	}

	@Override
	@SkipValidation
	public String add() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@SkipValidation
	public String edit() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String update() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@SkipValidation
	public String detail() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@SkipValidation
	public String delete() {
		// TODO Auto-generated method stub
		return null;
	}

	public String getNamaDebitur() {
		return namaDebitur;
	}

	public void setNamaDebitur(String namaDebitur) {
		this.namaDebitur = namaDebitur;
	}

	public Client getClient() {
		return client;
	}

	public void setClient(Client client) {
		this.client = client;
	}

	public List<Client> getListClient() {
		return listClient;
	}

	public void setListClient(List<Client> listClient) {
		this.listClient = listClient;
	}

	public String[] getSelectedRows() {
		return selectedRows;
	}

	public void setSelectedRows(String[] selectedRows) {
		this.selectedRows = selectedRows;
	}

	public String[] getSelectedAO() {
		return selectedAO;
	}

	public void setSelectedAO(String[] selectedAO) {
		this.selectedAO = selectedAO;
	}

	public List<User> getListAO() {
		return listAO;
	}

	public void setListAO(List<User> listAO) {
		this.listAO = listAO;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

}
